from direct.showbase.Loader import Loader
from panda3d.core import *
from direct.gui.OnscreenText import OnscreenText
from direct.actor.Actor import Actor
import random, sys, os, math
from direct.filter.CommonFilters import CommonFilters
from direct.filter.FilterManager import FilterManager
from direct.task import Task
from direct.interval.IntervalGlobal import *


def LoadMap(self,mapname):
        self.skydome = loader.loadModel("textures/skybox/dome.bam")
        self.skydome.setScale(200,200,100)
        self.skydome.reparentTo(render)
        self.skydome.setPos(0,0,-20)
        self.skydome.setBin('background', 0)
        self.skydome.setDepthWrite(0)
        self.skydome.setLightOff()
#        min, max = self.skydome.getTightBounds()
#        centre = (min+max) * 0.5
#        size = Vec3(max - min)/2
#        print size,centre
        self.terrain = loader.loadModel("maps/"+mapname+"/"+mapname)
       # self.terrain.setHpr(0,180,0)
        self.terrain.setPos(0,0,0)
        #self.terrain.setShader(Shader.load('shaders\BakedMaps.cg'))
        for tex in self.terrain.getChild(0).find("Mesh").findAllTextures():#Textures,Texcoords,Texturestages
            tex.setAnisotropicDegree(16)
        self.MapSpawnsCT = self.terrain.findAllMatches("**/Cstart*")
        self.MapSpawnsT = self.terrain.findAllMatches("**/Tstart*")
        print self.MapSpawnsT
        print self.MapSpawnsCT
        self.terrain.reparentTo(self.render)
        base.Physics1.LoadMapPhysics(mapname)
        base.r = 0.01
        base.g = 0.0601
        base.b = 0.0501
        if base.Player1.team == 0:#NOTE --- Forseeable problems this method needs expansion on server and client. 0 is ct
            pos = Point3(base.MapSpawnsCT[0].getPos()+Point3(0,0,1))
            switch = pos.getY()
            pos.y = -pos.getZ()
            pos.z = -switch
            base.Physics1.controller.setPos(Point3(pos))
        else:
            pos = Point3(base.MapSpawnsT[0].getPos()+Point3(0,0,1))
            switch = pos.getY()
            pos.y = -pos.getZ()
            pos.z = -switch
            base.Physics1.controller.setPos(Point3(pos))
def SkyScattering(task):
     g = Vec3(1,1,1)*0.1
     kr = Vec3(0.071,0.0601,0.0501)/10#Vec3(base.r,base.g,base.b)/10#Vec3(0.005,0.0005,0.0005)#*10
     km = Vec3(0.000001,0.000001,0.000001)
     sun = Vec4(1,1,1,1)*3
     brm = Vec3(math.pow(0.650,4),math.pow(0.510,4),math.pow(0.475,4))
     onebrm = Vec3(1/math.pow(0.650,4),1/math.pow(0.510,4),1/math.pow(0.475,4))
     pos =base.Player1.dummy.getPos()
     base.skydome.setShaderInput('eyePos',pos)
     base.skydome.setShaderInput('sunDirection',-base.dlnp.getMat().getRow3(1))#Vec3(0,0,1))#-base.Player1.dummy.getPos())#base.dlnp.getPos())
     base.skydome.setShaderInput('betaRayleighMie',brm)
     base.skydome.setShaderInput('reflectance',base.r,base.g,base.b,0)
     base.skydome.setShaderInput('HGg',g)
     base.skydome.setShaderInput('betaDashRay',kr)
     base.skydome.setShaderInput('betaDashMie',km)
     base.skydome.setShaderInput('oneOverBetaRM',onebrm)
     base.skydome.setShaderInput('sunColourIntensity',sun)
     base.skydome.setShaderInput('termMultipliers',1,1)
     return Task.cont
def LoadLights(self):
    self.lighting = True
    self.dlight = Spotlight('slight')
    self.dlight.getLens().setNearFar(1, 300)
    self.dlight.getLens().setFov(90)
    self.dlnp = self.render.attachNewNode(self.dlight)
    self.dlnp.setPos(Vec3(8,-9,8)*8)
    self.dlnp.lookAt(0,0,10)
    alight = AmbientLight('alight')
    alight.setColor(VBase4(0.2, 0.2, 0.2, 1))
    self.alnp = render.attachNewNode(alight)
    height = 40
    length = 20
    speed = 60
    base.dlnp.setPos(-30,length,height-20)
def UpdateOne(self):
    #if base.event.IsInView(base.watermesh):
      #  base.buffer.setActive(0)
    return Task.again
def Reflection(self):
        resolution = 1
        #generate mesh
        self.watermesh=render.attachNewNode("dummyNode")
        cm = CardMaker('card')
        for x in range(resolution):
            for y in range(resolution):
                card = render.attachNewNode(cm.generate())
                card.setPos(x,y,0)
                card.setHpr(0,-90,0)
                card.reparentTo(self.watermesh)
        base.watermesh.flattenStrong()
        #create reflection buffer
        samples = 1024
        self.rig = NodePath('rig')
        self.buffer = base.win.makeCubeMap('env', samples, self.rig)
        self.rig.reparentTo(render)
        self.rig.setPos(5,5,0)
        lens = self.rig.findAllMatches('**/+Camera')
        for i in range(len(lens)):
            lens[i].node().getLens().setNearFar(.1, 100)
            lens[i].node().setCameraMask(BitMask32.bit(0))
        base.watermesh.hide(BitMask32.bit(0))
        base.Player1.ownmodel.hide(BitMask32.bit(0))
        scale = 15
        self.watermesh.setScale(scale,scale,1)
        base.watermesh.setPos(-scale/2,-scale/2,0)
        cubemap = self.buffer.getTexture()
        cubemap.setMinfilter(Texture.FTLinearMipmapLinear)
        cubemap.setMagfilter(Texture.FTLinearMipmapLinear)
        bumpMap = loader.loadTexture("textures/skybox/bump_water.png")
        ts = TextureStage('ts')
        ts.setMode(TextureStage.MModulate)
        base.watermesh.setTexture(ts, bumpMap)
        base.watermesh.setShader(Shader.load('shaders\water_test.cg'))
        base.watermesh.setShaderInput('bump',bumpMap)
        base.watermesh.setShaderInput('etaRatio',0.66,1,1,1)
        base.watermesh.setShaderInput('param1',1.0,1.0,globalClock.getFrameTime(),globalClock.getFrameTime())
        base.watermesh.setShaderInput('texcube',self.buffer.getTexture())
        base.watermesh.setShaderInput('eyePositionW',base.camera.getPos(render))
        base.watermesh.setShaderInput('lightPos',base.dlnp.getPos())
        base.watermesh.hide()
    
def Bloom(self):
    filters = CommonFilters(base.win, base.cam)
    filters.setBloom(intensity = 1.0,desat = 0)

def ShadowMapping(self):
        ShadowMap=Texture()
        ShadowMap.setFormat(Texture.FDepthComponent) #to store depth value instead of color
        ShadowMap.setMinfilter(Texture.FTLinear)#Texture.FTShadow)     #to use OpenGL SGIX_shadow extension
        ShadowMap.setMagfilter(Texture.FTLinear)#Texture.FTShadow)
        ShadowMap.setWrapU(Texture.WMBorderColor)
        ShadowMap.setWrapV(Texture.WMBorderColor)
        ShadowMap.setBorderColor(Vec4(1,1,1,1))
        samples = 4
        self.mapsize = (1024*samples)
        base.LBuffer=base.win.makeTextureBuffer('depthmap',self.mapsize,self.mapsize,ShadowMap)
        self.LCam=base.makeCamera(base.LBuffer)
        self.LCam.node().setTagStateKey("ShadowCull")
        self.LCam.node().setTagState("True", RenderState.make(CullFaceAttrib.make(CullFaceAttrib.MCullNone)))
        base.terrain.setTag("ShadowCull", "True")
        self.LCam.node().setScene(render)
        self.LCam.reparentTo(self.dlnp)
        lens = OrthographicLens()
        self.LCam.node().setLens(lens)
        self.LCam.node().showFrustum()
        self.LCam.node().getLens().setFilmSize(120,120)
        self.LCam.node().getLens().setNearFar(1,1000)

        # default values
        self.pushBias=0.04
        self.ambient=0.5

        # setting up shader
        render.setShaderInput('light',self.LCam)
        render.setShaderInput('ShadowMap',ShadowMap)
        render.setShaderInput('AlphaMap',ShadowMap)
        render.setShaderInput('ambient',self.ambient,0,0,1.0)
        render.setShaderInput('texDisable',0,0,0,0)
        render.setShaderInput('scale',1,1,1,1)
        render.setShaderInput('samples',30)
        render.setShaderInput('push',self.pushBias,self.pushBias,self.pushBias,0)

        # Put a shader on the Light camera.
        lci = NodePath(PandaNode("Light Camera Initializer"))
        lci.setShader(Shader.load('shaders\caster.cg'))
        self.LCam.node().setInitialState(lci.getState())

         #Put a shader on the Main camera.
        mci = NodePath(PandaNode("Main Camera Initializer"))
        mci.setShader(Shader.load('shaders\Shadows_pcf_test.cg'))
        #Shadows_NVIDIA_PCF,Shadows_ATI_PCF,Shadows - 3 different shadow shaders
        base.cam.node().setInitialState(mci.getState())

